package com.tuanzi.loan.security;

import java.util.Collection;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import com.tuanzi.loan.business.entity.LoginUser;

@Component
public class LoanAccessDecisionManager implements AccessDecisionManager {

	@Override
	public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {

		if (configAttributes == null) {
			return;
		}

		if (authentication instanceof AnonymousAuthenticationToken) {
			throw new AccessDeniedException("Un-login user has no right to access system");
		}

		String requestURL = ((FilterInvocation) object).getRequestUrl();

		// 请求工作流页面都放行处理,通过工作流权限控制
		if (StringUtils.isNotBlank(requestURL) && StringUtils.startsWith(requestURL, "/views/process/")) {
			return;
		}

		LoginUser loginUser = (LoginUser) authentication.getPrincipal();
		for (String interceptUrl : loginUser.getInterceptUrls()) {
			if (!matchAntURL(interceptUrl, requestURL)) {
				continue;
			}
			return;
		}

		throw new AccessDeniedException(loginUser.getUsername() + " was trying to access " + requestURL + " without login successfully!");
	}

	private Boolean matchAntURL(String interceptUrl, String requestURL) {
		return new AntPathMatcher().match(interceptUrl + "/**", requestURL) || new AntPathMatcher().match(interceptUrl + "**", requestURL);
	}

	@Override
	public boolean supports(ConfigAttribute attribute) {
		return true;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

}
